package com.example;

import com.example.draw.DrawArrow;
import com.example.draw.DrawCircle;
import com.example.draw.DrawRectangle;
import com.example.draw.DrawShape;
import com.example.draw.DrawShapeFactory;
import com.example.jni.MouseListenerJNI;
import javafx.application.Platform;
import javafx.embed.swing.SwingFXUtils;
import javafx.scene.control.Button;
import javafx.scene.control.ColorPicker;
import javafx.scene.control.Label;
import javafx.scene.control.Slider;
import javafx.scene.image.PixelReader;
import javafx.scene.image.PixelWriter;
import javafx.scene.image.WritableImage;
import javafx.scene.input.Clipboard;
import javafx.scene.input.ClipboardContent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.layout.Background;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.robot.Robot;
import javafx.scene.shape.Rectangle;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.opencv.core.Mat;

import java.io.File;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * <p>提示工具</p>
 *
 * @author dc
 * @date 2025-09-16
 **/
public class ToolbarManager {
    private final PaneManager paneManager;
    private WritableImage fullScreenShot;

    private final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1, Executors.defaultThreadFactory());

    /**
     * 自动滚动任务
     */
    private ScheduledFuture<?> scrollTaskFuture;

    /**
     * 锁，避免并发点击
     */
    private final Object lock = new Object();
    /**
     * 是否点击选中区域
     */
    private boolean isClickSelectionRect = false;

    /**
     * 选中的形状
     */
    private DrawShape selectedShape;
    
    // 工具栏字段
    private final VBox toolbar;
    private Button confirmButton;
    private Button cancelButton;
    private Button saveButton;
    private Button editButton;
    private Button undoButton;
    private Button drawButton; // index=3
    private Button arrowButton; // index=2
    private Button circleButton; // index=1
    private Button rectButton; // index=0
    private Button moreButton;
    
    private int currentDrawButtonIndex = -1;

    private HBox drawBox;

    public ToolbarManager(PaneManager paneManager) {
        this.paneManager = paneManager;
        toolbar = createToolbar();
        // 安装鼠标监听钩子，监听选中区域的鼠标事件
        MouseListenerJNI listenerJni = MouseListenerJNI.getInstance();
        listenerJni.SetListenRect(0, 0, 0, 0);
        listenerJni.InstallMouseHook();
    }

    /**
     * 更新全屏截图，用于toolbar后续处理
     */
    public void setFullScreenShot(WritableImage fullScreenShot) {
        this.fullScreenShot = fullScreenShot;
    }

    /**
     * 创建工具栏方法
     */
    private VBox createToolbar() {
        VBox toolbar = new VBox(5);
        // 工具盒子
        HBox drawToolBox = new HBox(10);
        // 颜色粗细盒子
        HBox settingBox = new HBox(10);
        
        toolbar.setVisible(false);
        drawToolBox.setVisible(false);
        drawToolBox.setStyle("-fx-background-color: rgba(0, 0, 0, 0.8); -fx-padding: 10px; -fx-background-radius: 5px;");

        settingBox.setVisible(false);
        settingBox.setStyle("-fx-background-color: rgba(0, 0, 0, 0.8); -fx-padding: 10px; -fx-background-radius: 5px;");
        // 颜色选择器
        ColorPicker colorPicker = new ColorPicker(Color.RED);
        colorPicker.getCustomColors().addAll(Color.RED, Color.DEEPSKYBLUE, Color.LAWNGREEN, Color.ORANGE, Color.GREY, Color.WHITE);
        colorPicker.setStyle("-fx-color-label-visible: false ;");
        colorPicker.setOnAction(event -> {
            // 更新选中的形状颜色
            selectedShape.getShape().setStroke(colorPicker.getValue());
        });
        // 线条粗细滑块
        Label strokeLabel = new Label("粗细:");
        strokeLabel.setTextFill(Color.WHITE);
        Label colorLabel = new Label("颜色:");
        colorLabel.setTextFill(Color.WHITE);
        Slider strokeWidthSlider = new Slider(1, 7, 2);
        // 滑块自动匹配到刻度（不会处于刻度中间）
        strokeWidthSlider.setSnapToTicks(true);
        // 每隔几个数添加一个主刻度
        strokeWidthSlider.setMajorTickUnit(2);
        // 主刻度之间有多少小刻度
        strokeWidthSlider.setMinorTickCount(1);
        strokeWidthSlider.setShowTickLabels(true);
        strokeWidthSlider.setShowTickMarks(true);
        strokeWidthSlider.setOnMouseReleased(event -> {
            selectedShape.getShape().setStrokeWidth(strokeWidthSlider.getValue());
        });

        confirmButton = new Button("确认");
        cancelButton = new Button("取消");
        saveButton = new Button("保存");
        editButton = new Button("编辑");
        undoButton = new Button("撤销");
        drawButton = new Button("画笔");
        arrowButton = new Button("箭头");
        circleButton = new Button("圆形");
        rectButton = new Button("矩形");
        moreButton = new Button("截长图");
        drawBox = new HBox(10);
        drawBox.getChildren().addAll(rectButton, circleButton, arrowButton, drawButton);

        // 设置按钮样式
        String buttonStyle = "-fx-background-color: #4CAF50; -fx-text-fill: white; -fx-padding: 5px 15px;";
        confirmButton.setStyle(buttonStyle);
        cancelButton.setStyle(buttonStyle.replace("#4CAF50", "#f44336"));
        saveButton.setStyle(buttonStyle.replace("#4CAF50", "#2196F3"));
        editButton.setStyle(buttonStyle.replace("#4CAF50", "#3f51b5"));
        undoButton.setStyle(buttonStyle.replace("#4CAF50", "#9e9e9e"));
        drawButton.setStyle(buttonStyle.replace("#4CAF50", "#ff5722"));
        arrowButton.setStyle(buttonStyle.replace("#4CAF50", "#ff5722"));
        circleButton.setStyle(buttonStyle.replace("#4CAF50", "#ff5722"));
        rectButton.setStyle(buttonStyle.replace("#4CAF50", "#ff5722"));
        moreButton.setStyle(buttonStyle.replace("#4CAF50", "#9c27b0"));
        // 隐藏编辑按钮
        editButton.setVisible(false);
        // 不占用父布局空间
        editButton.setManaged(false);

        settingBox.getChildren().addAll(colorLabel, colorPicker, strokeLabel, strokeWidthSlider);
        drawToolBox.getChildren().addAll(drawBox, undoButton, moreButton, editButton, saveButton, cancelButton, confirmButton);
        toolbar.getChildren().addAll(drawToolBox, settingBox);
        
        return toolbar;
    }

    public VBox getToolbar() {
        return toolbar;
    }
    public DrawShape getSelectedShape() {
        return selectedShape;
    }
    public HBox getToolBox() {
        return (HBox) toolbar.getChildren().get(0);
    }
    public HBox getSettingBox() {
        return (HBox) toolbar.getChildren().get(1);
    }
    public void updateSettingBox() {
        HBox settingBox = (HBox)toolbar.getChildren().get(1);
        ColorPicker colorPicker = (ColorPicker)settingBox.getChildren().get(1);
        Slider strokeWidthSlider = (Slider)settingBox.getChildren().get(3);
        colorPicker.setValue(selectedShape.getDrawColor());
        strokeWidthSlider.setValue(selectedShape.getDrawThickness());
    }

    /**
     * 显示工具栏
     * @param x      选择区域左上点的x坐标
     * @param y      选择区域左上点的y坐标
     * @param width  选择区域的宽度
     * @param height 选择区域高度
     */
    public void showToolbar(double x, double y, double width, double height) {
        // 计算容器位置（让容器右边界与选择区域右边界对齐）
        double containerX = x + width - toolbar.getWidth();
        double containerY = y + height + 10;

        // 确保工具栏不会超出屏幕边界
        if (containerX < 10) {
            containerX = 10;
        }
        if (containerX + toolbar.getWidth() > CaptureProperty.screenWidth) {
            containerX = CaptureProperty.screenWidth - toolbar.getWidth() - 10;
        }
        if (containerY + toolbar.getHeight() > CaptureProperty.screenHeight) {
            containerY = containerY - toolbar.getHeight() - 10;
        }

        // 设置容器位置
        AnchorPane.setLeftAnchor(toolbar, containerX);
        AnchorPane.setTopAnchor(toolbar, containerY);
        
        // 显示工具栏
        toolbar.setVisible(true);
        getToolBox().setVisible(true);
        
        // 工具栏中的按钮显示控制
        moreButton.setVisible(true);
        moreButton.setManaged(true);
        drawBox.setVisible(true);
        drawBox.setManaged(true);
        undoButton.setVisible(true);
        undoButton.setManaged(true);
        editButton.setVisible(false);
        editButton.setManaged(false);

        // 选择的区域和起始坐标都是基于逻辑分辨率，需要乘以缩放比例来定位到实际物理像素，这样裁剪的图片才符合选中的区域
        double physicalX = x * CaptureProperty.scaleX;
        double physicalY = y * CaptureProperty.scaleY;
        double physicalWidth = width * CaptureProperty.scaleX;
        double physicalHeight = height * CaptureProperty.scaleY;

        // 绑定按钮事件
        bindToolbarEvents(physicalX, physicalY, physicalWidth, physicalHeight);
    }

    private void bindToolbarEvents(double x, double y, double width, double height) {
        confirmButton.setOnAction(e -> {
            copySelectedArea(x, y, width, height);
            closeCurrentWindow();
        });

        cancelButton.setOnAction(e -> {
            closeCurrentWindow();
        });

        saveButton.setOnAction(e -> {
            saveSelectedArea(x, y, width, height);
        });
        
        editButton.setOnAction(e -> { 
            drawBox.setVisible(true);
            drawBox.setManaged(true);
            editButton.setVisible(false);
            editButton.setManaged(false);
        });
        
        undoButton.setOnAction(e -> {
            paneManager.getDrawStackManager().removeShape();
        });

        rectButton.setOnAction(e -> {
            // 当前按钮再次点击隐藏颜色粗细设置框
            if (currentDrawButtonIndex == 0) {
                getSettingBox().setVisible(!getSettingBox().isVisible());
                return;
            }
            currentDrawButtonIndex = 0;
            CaptureProperty.isDrawing = true;
            selectedShape = DrawRectangle.getSingleInstance();
            updateSettingBox();
            getSettingBox().setVisible(true);
        });
        circleButton.setOnAction(e -> {
            if (currentDrawButtonIndex == 1) {
                getSettingBox().setVisible(!getSettingBox().isVisible());
                return;
            }
            currentDrawButtonIndex = 1;
            CaptureProperty.isDrawing = true;
            selectedShape = DrawCircle.getSingleInstance();
            updateSettingBox();
            getSettingBox().setVisible(true);
        });
        arrowButton.setOnAction(e -> {
            if (currentDrawButtonIndex == 2) {
                getSettingBox().setVisible(!getSettingBox().isVisible());
                return;
            }
            currentDrawButtonIndex = 2;
            CaptureProperty.isDrawing = true;
            selectedShape = DrawArrow.getSingleInstance();
            updateSettingBox();
            getSettingBox().setVisible(true);
        });

        moreButton.setOnAction(e -> {
            if (height < CaptureProperty.SCROLL_FRAME_HEIGHT) {
                // 提示选择区域高度不够，重新选择
                HintPopup.showPopup(paneManager.getCaptureStage(), "选择区域高度不够，请重新选择");
                return;
            }
            moreButton.setVisible(false);
            moreButton.setManaged(false);
            drawBox.setVisible(false);
            drawBox.setManaged(false);
            undoButton.setVisible(false);
            undoButton.setVisible(false);
            editButton.setVisible(true);
            editButton.setManaged(true);
            
            CaptureProperty.isScrollingActive = true;
            // 每次创建一个新的滚动处理器，这样就不用手动重置上一次记录的数据了
            ScrollHandler.createNewScrollHandler();
            enableMouseHook(x, y, width, height);
        });
    }

    /**
     * 截取选择区域
     *
     * @param x      选择区域左上点的x坐标
     * @param y      选择区域左上点的y坐标
     * @param width  选择区域的宽度
     * @param height 选择区域高度
     */
    private WritableImage getSelectedArea(double x, double y, double width, double height) {
        WritableImage selectedArea = new WritableImage((int) width, (int) height);
        PixelReader reader = fullScreenShot.getPixelReader();
        PixelWriter writer = selectedArea.getPixelWriter();

        for (int i = 0; i < (int) width; i++) {
            for (int j = 0; j < (int) height; j++) {
                Color color = reader.getColor((int) x + i, (int) y + j);
                writer.setColor(i, j, color);
            }
        }
        return selectedArea;
    }

    /**
     * 复制选择区域
     *
     * @param x      选择区域左上点的x坐标
     * @param y      选择区域左上点的y坐标
     * @param width  选择区域的宽度
     * @param height 选择区域的高度
     */
    private void copySelectedArea(double x, double y, double width, double height) {
        WritableImage selectedArea = getSelectedArea(x, y, width, height);
        Clipboard clipboard = Clipboard.getSystemClipboard();
        ClipboardContent content = new ClipboardContent();
        content.putImage(selectedArea);
        clipboard.setContent(content);
    }

    /**
     * 保存选择区域
     *
     * @param x      选择区域左上点的x坐标
     * @param y      选择区域左上点的y坐标
     * @param width  选择区域的宽度
     * @param height 选择区域的高度
     */
    private void saveSelectedArea(double x, double y, double width, double height) {
        try {
            MouseListenerJNI.getInstance().disableMouseHook();
            // 保存到文件
            FileChooser fileChooser = new FileChooser();
            fileChooser.setTitle("保存截图");
            fileChooser.setInitialFileName("screenshot" + System.currentTimeMillis() + ".png");
            fileChooser.getExtensionFilters().add(
                    new FileChooser.ExtensionFilter("PNG Files", "*.png"));

            File file = fileChooser.showSaveDialog(paneManager.getCaptureStage());
            java.awt.image.BufferedImage bufferedImage;
            if (file != null) {
                if (CaptureProperty.isScrollingActive) {
                    Mat resultMat = ImageStitcher.rollStitchImages(ScrollHandler.getScrollHandler().getDownScrollFrameList());
                    bufferedImage = SwingFXUtils.fromFXImage(ImageConverter.matToWriteableImage(resultMat), null);
                } else {
                    SwingFXUtils.fromFXImage(getSelectedArea(x, y, width, height), null);
                    bufferedImage = SwingFXUtils.fromFXImage(getSelectedArea(x, y, width, height), null);
                }
                javax.imageio.ImageIO.write(bufferedImage, "png", file);
                System.out.println("截图已保存到: " + file.getAbsolutePath());
                closeCurrentWindow();
            } else {
                MouseListenerJNI.getInstance().enableMouseHook();
            }

        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }

    /**
     * <p>滚动截图。</p>
     * <p>不同程序间的窗口无法传递滚动事件，
     * 被选择区域如果设置 <code>Color.TRANSPARENT</code> ，就无法再捕获事件，选择区域会成为真正的空洞，点击和滚动均会使得焦点转移到空洞后的其它程序窗口，
     * 此时鼠标可对其它程序的窗口进行各种操作，这不是一个好的现象，只能滚动才是我们想要的；<br>
     * 为此通过jni实现了一个全局的鼠标钩子，可在鼠标事件生效前进行操作，此鼠标钩子会拦截选择区域内的点击和滚动事件，
     * 点击事件触发时会使其无效并通过{@link MouseListenerJNI#mouseScrollCallBack(int)}通知给java程序，
     * 而滚动事件则是通过一个限流函数限制滚动速度，并通过{@link MouseListenerJNI#mouseScrollCallBack(int)}通知给java程序。
     * 
     * @param x      选择区域左上点的x坐标
     * @param y      选择区域左上点的y坐标
     * @param width  选择区域的宽度
     * @param height 选择区域的高度
     */
    private void enableMouseHook(double x, double y, double width, double height) {
        // 取消背景阻挡，让选定区域可滚动
        paneManager.getRootPane().setBackground(Background.EMPTY);
        
        // 安装鼠标监听钩子，监听选中区域的鼠标事件
        MouseListenerJNI listenerJni = MouseListenerJNI.getInstance();
        listenerJni.SetListenRect((int) x, (int) y, (int) (x + width), (int) (y + height));
        listenerJni.enableMouseHook();

        // 保存初始截图
        Platform.runLater(() -> {
            ScrollHandler scrollHandler = ScrollHandler.getScrollHandler();
            WritableImage frame = scrollHandler.getFrame();
            Mat frameMat = ImageConverter.writeableImageToMat(frame);
            scrollHandler.saveFrame(frameMat, 1);
        });
        
    }
    /**
     * 点击选中区域自动滚动控制
     */
    public void autoScrollControl() {
        Rectangle selectionRect = paneManager.getSelectionRect();
        // 加锁防止快速点击导致多次提交定时任务
        synchronized (lock) {
            // 如果已经点击了选定区域，再次点击则取消自动滑动
            if (isClickSelectionRect) {
                scrollTaskFuture.cancel(true);
                // 重置点击状态
                isClickSelectionRect = false;
                // 直接返回避免继续提交滑动任务
                return;
            }
            isClickSelectionRect = true;

            // 添加定时任务，每隔一段时间滚动一次，定时滚动会触发setOnScroll滚动监听
            // 时间间隔越大，用户点击到蒙层的概率越大，如果用户没成功点击到蒙层，则会停止滚动失败
            scrollTaskFuture = executorService.scheduleAtFixedRate(() -> {
                // 让robot操作运行于JavaFX UI线程，Platform.runLater需处于任务内部，如果在任务外面则robot操作依然在其它线程中，会导致robot操作失败
                Platform.runLater(() -> {
                    Robot robot = new Robot();
                    // 如果鼠标在选中区域内
                    if (robot.getMouseX() > selectionRect.getX() && 
                            robot.getMouseX() < selectionRect.getX() + selectionRect.getWidth() &&
                            robot.getMouseY() > selectionRect.getY() && 
                            robot.getMouseY() < selectionRect.getY() + selectionRect.getHeight()) {
                        robot.mouseWheel(1);
                    } else {
                        System.out.println("鼠标不在选中区域");
                        // 鼠标不在选中区域，则取消自动滑动
                        scrollTaskFuture.cancel(true);
                        // 重置点击状态
                        isClickSelectionRect = false;
                    }
                });
            }, 0, 300, TimeUnit.MILLISECONDS);
        }
    }
    

    /**
     * 清除选择区域和工具栏
     */
    public void clearArea() {
        Rectangle selectionRect = paneManager.getSelectionRect();
        selectionRect.setVisible(false);
        selectionRect.setWidth(0);
        selectionRect.setHeight(0);
        // 清理绘制栈
        paneManager.getDrawStackManager().getDrawShapeStack().setVisible(false);
        paneManager.getDrawStackManager().clearStack();

        DrawShapeFactory.clearSingleInstances();
        
        if (scrollTaskFuture != null) {
            scrollTaskFuture.cancel(true);
        }

        toolbar.setVisible(false);
        getSettingBox().setVisible(false);
    }

    /**
     * 通用的关闭当前窗口方法
     */
    public void closeCurrentWindow() {
        clearArea();

        Stage captureStage = paneManager.getCaptureStage();
        if (captureStage != null) {
            captureStage.close();
        }
        CaptureProperty.isCaptureActive = false;
        CaptureProperty.isScrollingActive = false;
        CaptureProperty.isSelected = false;
        CaptureProperty.isDrawing = false;
        currentDrawButtonIndex = -1;

        // 禁用鼠标监听钩子
        MouseListenerJNI.getInstance().disableMouseHook();
        
        System.out.println("截图完成，状态已重置");
    }

    public void closeThreadPool() {
        executorService.shutdownNow();
    }

}
